from typing import Any, List, Optional
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.orm import Session
from database import get_db
from models import Department, User
from schemas import DepartmentCreate, DepartmentUpdate, DepartmentSchema, ResponseModel, PaginatedResponse
from api.deps import get_current_active_user, get_current_superuser

router = APIRouter()

# 递归构建部门树形结构
def build_department_tree(departments, parent_id=None):
    tree = []
    for department in departments:
        if department.parent_id == parent_id:
            children = build_department_tree(departments, department.id)
            department_dict = department.__dict__.copy()
            department_dict.pop('_sa_instance_state', None)
            department_dict['children'] = children
            tree.append(department_dict)
    return tree

@router.get("", response_model=ResponseModel[List[DepartmentSchema]])
def get_departments(
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db)
) -> Any:
    """获取部门树形结构"""
    departments = db.query(Department).all()
    department_tree = build_department_tree(departments)
    return ResponseModel(data=department_tree)

@router.get("/list", response_model=ResponseModel[PaginatedResponse[DepartmentSchema]])
def get_departments_list(
    page: int = Query(1, ge=1, description="页码"),
    page_size: int = Query(10, ge=1, le=100, description="每页数量"),
    name: Optional[str] = Query(None, description="部门名称搜索"),
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db)
) -> Any:
    """获取部门列表（分页）"""
    query = db.query(Department)
    
    if name:
        query = query.filter(Department.name.contains(name))
    
    # 计算总数
    total = query.count()
    
    # 分页
    departments = query.offset((page - 1) * page_size).limit(page_size).all()
    
    return ResponseModel(
        data=PaginatedResponse(
            total=total,
            page=page,
            page_size=page_size,
            items=departments
        )
    )

@router.get("/{department_id}", response_model=ResponseModel[DepartmentSchema])
def get_department(
    department_id: int,
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db)
) -> Any:
    """获取部门详情"""
    department = db.query(Department).filter(Department.id == department_id).first()
    if not department:
        raise HTTPException(
            status_code=404,
            detail="部门不存在"
        )
    
    return ResponseModel(data=department)

@router.post("", response_model=ResponseModel[DepartmentSchema])
def create_department(
    department_in: DepartmentCreate,
    current_user: User = Depends(get_current_superuser),
    db: Session = Depends(get_db)
) -> Any:
    """创建部门"""
    # 检查部门名是否已存在
    department = db.query(Department).filter(Department.name == department_in.name).first()
    if department:
        raise HTTPException(
            status_code=400,
            detail="部门名称已存在"
        )
    
    # 检查父部门是否存在
    if department_in.parent_id:
        parent_department = db.query(Department).filter(Department.id == department_in.parent_id).first()
        if not parent_department:
            raise HTTPException(
                status_code=400,
                detail="父部门不存在"
            )
    
    # 创建新部门
    db_department = Department(
        name=department_in.name,
        leader=department_in.leader,
        phone=department_in.phone,
        description=department_in.description,
        parent_id=department_in.parent_id
    )
    
    db.add(db_department)
    db.commit()
    db.refresh(db_department)
    
    return ResponseModel(data=db_department)

@router.put("/{department_id}", response_model=ResponseModel[DepartmentSchema])
def update_department(
    department_id: int,
    department_in: DepartmentUpdate,
    current_user: User = Depends(get_current_superuser),
    db: Session = Depends(get_db)
) -> Any:
    """更新部门"""
    department = db.query(Department).filter(Department.id == department_id).first()
    if not department:
        raise HTTPException(
            status_code=404,
            detail="部门不存在"
        )
    
    # 检查部门名是否已存在（排除当前部门）
    if department_in.name and department_in.name != department.name:
        existing_department = db.query(Department).filter(Department.name == department_in.name).first()
        if existing_department:
            raise HTTPException(
                status_code=400,
                detail="部门名称已存在"
            )
    
    # 检查父部门是否存在，且不能设置为自己或其子部门
    if department_in.parent_id is not None:
        # 不能设置为自己
        if department_in.parent_id == department_id:
            raise HTTPException(
                status_code=400,
                detail="不能将部门设置为自己的子部门"
            )
        
        # 检查父部门是否存在
        parent_department = db.query(Department).filter(Department.id == department_in.parent_id).first()
        if not parent_department:
            raise HTTPException(
                status_code=400,
                detail="父部门不存在"
            )
        
        # 检查是否会形成循环引用
        def is_descendant(child_id, parent_id):
            # 检查child_id是否是parent_id的子部门
            child_departments = db.query(Department).filter(Department.parent_id == child_id).all()
            for child in child_departments:
                if child.id == parent_id or is_descendant(child.id, parent_id):
                    return True
            return False
        
        if is_descendant(department_id, department_in.parent_id):
            raise HTTPException(
                status_code=400,
                detail="不能将部门设置为其子部门的子部门"
            )
    
    # 更新字段
    update_data = department_in.dict(exclude_unset=True)
    for field, value in update_data.items():
        setattr(department, field, value)
    
    db.commit()
    db.refresh(department)
    
    return ResponseModel(data=department)

@router.delete("/{department_id}", response_model=ResponseModel[dict])
def delete_department(
    department_id: int,
    current_user: User = Depends(get_current_superuser),
    db: Session = Depends(get_db)
) -> Any:
    """删除部门"""
    department = db.query(Department).filter(Department.id == department_id).first()
    if not department:
        raise HTTPException(
            status_code=404,
            detail="部门不存在"
        )
    
    # 检查是否有子部门
    child_departments = db.query(Department).filter(Department.parent_id == department_id).all()
    if child_departments:
        raise HTTPException(
            status_code=400,
            detail="该部门下还有子部门，无法删除"
        )
    
    # 检查是否有用户在该部门
    users = db.query(User).filter(User.department_id == department_id).all()
    if users:
        raise HTTPException(
            status_code=400,
            detail="该部门下还有用户，无法删除"
        )
    
    db.delete(department)
    db.commit()
    
    return ResponseModel(data={"message": "部门删除成功"})